package com.xiashitech.agent.instrumentation.redis.lettuce;

import com.xiashitech.agent.config.StartConfig;
import com.xiashitech.agent.constants.Instrumentation;
import com.xiashitech.agent.dto.UserRequest;
import com.xiashitech.agent.instrumentation.base.DebugUtils;
import com.xiashitech.agent.instrumentation.base.InstProcessor;
import com.xiashitech.agent.instrumentation.base.context.TraceContextVars;
import com.xiashitech.agent.instrumentation.bridge.Java8Bridge;
import com.xiashitech.agent.instrumentation.redis.RedisData;
import com.xiashitech.agent.instrumentation.utils.BaggageUtil;
import com.xiashitech.agent.instrumentation.utils.MachineAttributesUtil;
import com.xiashitech.interfaces.agent.dto.SystemInfoDTO;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.baggage.Baggage;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.Attributes;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.javaagent.shaded.io.opentelemetry.context.Context;

import javax.annotation.Nullable;
import java.util.Optional;

/**
 * lettuce获取userId的逻辑处理器
 */
public class XSLettuceProcessor extends InstProcessor<RedisData, Object> {

    public XSLettuceProcessor(String spanName) {
        super(spanName);
    }

    @Override
    public void onXSStart(AttributesBuilder attributesBuilder, Context context, RedisData redisData) {

    }

    @Override
    public Context setBaggageAndContext(Context context, RedisData redisData, Attributes attributes) {
        // context = updateBaggage(context, builder -> builder.put("key", "value"));
        return context;
    }

    @Override
    public void onXSEnd(AttributesBuilder attributesBuilder, Context context, RedisData redisDataRequest, Object value, @Nullable Throwable throwable) {
        //DebugUtils.print4Debug("XSLettuceProcessor.onXSEnd");

        if(value instanceof byte[]) {
            if (redisDataRequest.getRedisOpetion().equals(Instrumentation.Redis_Opetion_Get)) {
                redisDataRequest.setValue((byte[])value);
            }

            DebugUtils.print4Debug("XSLettuceProcessor.redisData", redisDataRequest);

            if(redisDataRequest.getValue() != null) {
                Baggage baggage = Baggage.fromContext(context);
                try {
                    Optional<UserRequest> redisDataOptional = Java8Bridge.executeRuleForUserInfoMatchRule(redisDataRequest);
                    if (redisDataOptional.isPresent()) {
                        UserRequest userRequest = redisDataOptional.get();
                        setAttributes(attributesBuilder, userRequest, baggage, false);
                    }
                } catch (Throwable e) {
                    DebugUtils.printError4Debug(e);
                }
            }
        }

        MachineAttributesUtil.fillMachineAttributes(attributesBuilder);
    }

    private void setAttributes(AttributesBuilder attributes, UserRequest userRequest, Baggage baggage, Boolean sessionUpdate) {
        try {
            attributes.put("xs.userId", userRequest.getUserid() == null ? "" : userRequest.getUserid());
            attributes.put("xs.sessionId", userRequest.getSessionId() == null ? "" : userRequest.getSessionId());
            attributes.put("xs.requestDate", userRequest.getRequestDate() == null ? "" : userRequest.getRequestDate().toString());
            attributes.put("xs.sessionUpdate", sessionUpdate);
            attributes.put("xs.systemId", StartConfig.getParamValueFromKey(StartConfig.systemId));
            attributes.put("xs.systemReg", SystemInfoDTO.getConfig().getSystemExist());
            attributes.put("xs.sourceSystemId", baggage.getEntryValue("xsAuthSystemId") == null ? StartConfig.getParamValueFromKey(StartConfig.systemId) : baggage.getEntryValue("xsAuthSystemId"));

            TraceContextVars.get()
                    .set("xs.userId", userRequest.getUserid() == null ? "" : userRequest.getUserid())
                    .set("endpoint-api", baggage.getEntryValue("endpoint-api") == null ? "" : baggage.getEntryValue("endpoint-api"))
                    .set("xs.sessionId", userRequest.getSessionId() == null ? "" : userRequest.getSessionId())
                    .set("xs.requestDate", userRequest.getRequestDate() == null ? "" : userRequest.getRequestDate().toString())
                    .set("xs.sessionUpdate", sessionUpdate.toString());
        } catch (Throwable e) {
            DebugUtils.printError4Debug(e);
        }
    }
}
